#include "sht3x_if.h"

#include "securec.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "hdf_io_service_if.h"

#include <unistd.h>

#define HDF_LOG_TAG sht3x_if

struct sht3x_dev {
    void *object;
};

DevHandle sht3xOpen(uint32_t num)
{
    struct sht3x_dev *dev = NULL;
    int32_t ret;
    char *serviceName = NULL;
    struct HdfIoService *service = NULL;

    // 初始化操作句柄
    dev = (struct sht3x_dev *)OsalMemCalloc(sizeof(struct sht3x_dev));
    if (dev == NULL) {
        HDF_LOGE("Failed to OsalMemCalloc handle.");
        goto sht3x_open_fail;
    }

    // 初始化服务句柄
    serviceName = (char *)OsalMemCalloc(MAX_DEV_NAME_SIZE);
    if (serviceName == NULL) {
        HDF_LOGE("Failed to OsalMemCalloc serviceName.");
        goto sht3x_open_fail;
    }

    // 获取设备服务名
    ret = snprintf_s(serviceName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, SHT3X_DEV_SERVICE_NAME_PREFIX, num);
    if (ret < 0) {
        HDF_LOGE("Failed to snprintf_s.");
        goto sht3x_open_fail;
    }

    // 绑定服务
    service = HdfIoServiceBind(serviceName);
    if (service == NULL) {
        printf("Failed to get service %s.", serviceName);
        goto sht3x_open_fail;
    }

    // 释放空间
    OsalMemFree(serviceName);
    dev->object = service;
    return (DevHandle)dev;

sht3x_open_fail:

    if (serviceName) {
        OsalMemFree(serviceName);
    }

    if (dev) {
        OsalMemFree(dev);
    }

    return NULL;
}

// 关闭设备
void sht3xClose(DevHandle dev)
{
    struct HdfIoService *service = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    if (sht3x == NULL) {
        return;
    }

    if (sht3x->object != NULL) {
        // service = (struct HdfIoService *)sht3x->object;
        // service->dispatcher->Dispatch(&service->object, SHT3X_CMD_DISABLE, NULL, NULL);
        HdfIoServiceRecycle(service);
        OsalMemFree(sht3x);
    }
}

// 设置设备工作模式
int32_t sht3xSetMode(DevHandle dev, uint8_t mode)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct HdfSBuf *sBuf = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_set_mode_exit;
    }

    // 创建sbuf
    sBuf = HdfSBufObtainDefaultSize();
    if (sBuf == NULL) {
        HDF_LOGE("Failed to obtain sBuf.");
        ret = HDF_FAILURE;
        goto sht3x_set_mode_exit;
    }

    // 设置工作模式
    if (!HdfSbufWriteUint8(sBuf, mode)){
        HDF_LOGE("Failed to write sbuf.");
        ret = HDF_FAILURE;
        goto sht3x_set_mode_exit;
    }

    // 获取句柄
    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_SET_MODE, sBuf, NULL);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        goto sht3x_set_mode_exit;
    }

sht3x_set_mode_exit:

    if (sBuf) {
        HdfSBufRecycle(sBuf);
    }

    return ret;
}

// 读取测量的温湿度数据
int32_t sht3xGetData(DevHandle dev, sht3x_data *data)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct HdfSBuf *rBuf = NULL;
    uint32_t data_len = 0;
    char *temp = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL || data == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_get_data_exit;
    }

    // 创建rBuf
    rBuf = HdfSBufObtainDefaultSize();
    if (rBuf == NULL) {
        HDF_LOGE("Failed to obtain rBuf.");
        ret = HDF_FAILURE;
        goto sht3x_get_data_exit;
    }

    // 获取句柄
    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_GET_TEMP_HUMI, NULL, rBuf);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        ret = HDF_FAILURE;
        goto sht3x_get_data_exit;
    }

    // 获取数据
    if (!HdfSbufReadBuffer(rBuf, (const void *)&temp, &data_len)) {
        HDF_LOGE("Failed to read rBuf.");
        ret = HDF_FAILURE;
        goto sht3x_get_data_exit;
    }

    // 拷贝数据
    memcpy_s(data, sizeof(sht3x_data), temp, data_len);

sht3x_get_data_exit:

    if (rBuf) {
        HdfSBufRecycle(rBuf);
    }

    return ret;
}

// 获取温度数据
int32_t sht3xGetTempData(DevHandle dev, float *temperature)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct HdfSBuf *rBuf = NULL;
    uint32_t data_len = 0;
    char *temp = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL || temperature == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_get_temp_data_exit;
    }

    // 创建rBuf
    rBuf = HdfSBufObtainDefaultSize();
    if (rBuf == NULL) {
        HDF_LOGE("Failed to obtain rBuf.");
        ret = HDF_FAILURE;
        goto sht3x_get_temp_data_exit;
    }

    // 获取句柄
    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_GET_TEMP, NULL, rBuf);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        ret = HDF_FAILURE;
        goto sht3x_get_temp_data_exit;
    }

    // 获取数据
    if (!HdfSbufReadBuffer(rBuf, (const void *)&temp, &data_len)) {
        HDF_LOGE("Failed to read rBuf.");
        ret = HDF_FAILURE;
        goto sht3x_get_temp_data_exit;
    }

    // 拷贝数据
    memcpy_s(temperature, sizeof(float), temp, data_len);

sht3x_get_temp_data_exit:

    if (rBuf) {
        HdfSBufRecycle(rBuf);
    }

    return ret;
}

// 获取湿度数据
int32_t sht3xGetHumiData(DevHandle dev, float *humidity)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct HdfSBuf *rBuf = NULL;
    uint32_t data_len = 0;
    char *temp = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL || humidity == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_get_humi_data_exit;
    }

    // 创建rBuf
    rBuf = HdfSBufObtainDefaultSize();
    if (rBuf == NULL) {
        HDF_LOGE("Failed to obtain rBuf.");
        ret = HDF_FAILURE;
        goto sht3x_get_humi_data_exit;
    }

    // 获取句柄
    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_GET_HUMI, NULL, rBuf);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        ret = HDF_FAILURE;
        goto sht3x_get_humi_data_exit;
    }

    // 获取数据
    if (!HdfSbufReadBuffer(rBuf, (const void *)&temp, &data_len)) {
        HDF_LOGE("Failed to read rBuf.");
        ret = HDF_FAILURE;
        goto sht3x_get_humi_data_exit;
    }

    // 拷贝数据
    memcpy_s(humidity, sizeof(float), temp, data_len);

sht3x_get_humi_data_exit:

    if (rBuf) {
        HdfSBufRecycle(rBuf);
    }

    return ret;
}

// 设置采样间隔
int32_t sht3xSetSamplingInterval(DevHandle dev, int64_t interval)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct HdfSBuf *sBuf = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_set_sampling_interval_exit;
    }

    // 创建sbuf
    sBuf = HdfSBufObtainDefaultSize();
    if (sBuf == NULL) {
        HDF_LOGE("Failed to obtain sBuf.");
        ret = HDF_FAILURE;
        goto sht3x_set_sampling_interval_exit;
    }

    // 设置采样间隔
    if (!HdfSbufWriteInt64(sBuf, interval)) {
        HDF_LOGE("Failed to write sbuf.");
        ret = HDF_FAILURE;
        goto sht3x_set_sampling_interval_exit;
    }

    // 获取句柄
    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_SET_SAMPLING_INTERVAL, sBuf, NULL);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        goto sht3x_set_sampling_interval_exit;
    }

sht3x_set_sampling_interval_exit:

    if (sBuf) {
        HdfSBufRecycle(sBuf);
    }

    return ret;
}

// 使能设备
int32_t sht3xEnable(DevHandle dev)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_enable_exit;
    }

    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_ENABLE, NULL, NULL);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        ret = HDF_FAILURE;
    }

sht3x_enable_exit:
    return ret;
}

int32_t sht3xDisable(DevHandle dev)
{
    int32_t ret = HDF_SUCCESS;
    struct HdfIoService *service = NULL;
    struct sht3x_dev *sht3x = (struct sht3x_dev *)dev;

    // 参数检查
    if (sht3x == NULL || sht3x->object == NULL) {
        HDF_LOGE("handle or handle->object is NULL.");
        ret = HDF_ERR_INVALID_OBJECT;
        goto sht3x_disable_exit;
    }

    service = (struct HdfIoService *)sht3x->object;
    ret = service->dispatcher->Dispatch(&service->object, SHT3X_CMD_DISABLE, NULL, NULL);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Failed to send service call.");
        ret = HDF_FAILURE;
    }

sht3x_disable_exit:
    return ret;
}
